package com.zxy.study.ui.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager2.widget.ViewPager2;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.zxy.study.R;
import com.zxy.study.base.recyclerview.BaseViewHolder;
import com.zxy.study.utils.DimenUtils;

import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;


/**
 * desc   : BlueBannerView
 * author : Brice.Zhang
 * email  : brice.zhang@mart.blue
 * time   : 2019/7/26 14:47
 */
public class BlueBannerView extends FrameLayout {

    private ViewPager2 mViewPager;
    private BlueBannerAdapter2 mBannerAdapter;
    private LinearLayout mIndicatorLayout;
    private View[] mIndicatorViews;

    private static final ImageView.ScaleType[] sScaleTypeArray = {
            ImageView.ScaleType.MATRIX,
            ImageView.ScaleType.FIT_XY,
            ImageView.ScaleType.FIT_START,
            ImageView.ScaleType.FIT_CENTER,
            ImageView.ScaleType.FIT_END,
            ImageView.ScaleType.CENTER,
            ImageView.ScaleType.CENTER_CROP,
            ImageView.ScaleType.CENTER_INSIDE
    };

    private boolean mShowIndicator;
    private int mIndicatorColor;
    private int mIndicatorSelectColor;
    private int mIndicatorSize;
    private int mIndicatorPadding;
    private int mIndicatorBottomMargin;
    private int mCornerRadius = 4;
    private ImageView.ScaleType mScaleType;

    private boolean mEnableAutoPlay = true;
    private boolean mIsAutoPlaying = false;
    private int mAutoPlayTime = 5000;
    private List<String> mUrlList;
    private BlueBannerHandler mHandler = new BlueBannerHandler(this);

    private OnItemClickListener mOnItemClickListener;
    private OnItemExposureListener mOnItemExposureListener;

    public interface OnItemClickListener {
        void onItemClick(String url, int position);
    }

    public interface OnItemExposureListener {
        void onItemExposure(String url, int position);
    }

    public BlueBannerView(@NonNull Context context) {
        this(context, null);
    }

    public BlueBannerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BlueBannerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray ta = context.getResources().obtainAttributes(attrs, R.styleable.BlueBannerView);
        mShowIndicator = ta.getBoolean(R.styleable.BlueBannerView_bv_showIndicator, true);
        mIndicatorColor = ta.getColor(R.styleable.BlueBannerView_bv_indicatorColor,
                Color.parseColor("#80FFFFFF"));
        mIndicatorSelectColor = ta.getColor(R.styleable.BlueBannerView_bv_indicatorSelectColor,
                Color.parseColor("#FFFFFFFF"));
        mIndicatorSize = ta.getDimensionPixelSize(R.styleable.BlueBannerView_bv_indicatorSize,
                DimenUtils.dpToPx(context, 4));
        mIndicatorPadding = ta.getDimensionPixelSize(R.styleable.BlueBannerView_bv_indicatorPadding,
                DimenUtils.dpToPx(context, 10));
        mIndicatorBottomMargin = ta.getDimensionPixelOffset(R.styleable.BlueBannerView_bv_indicatorBottomMargin,
                DimenUtils.dpToPx(context, 8));
        mCornerRadius = ta.getDimensionPixelOffset(R.styleable.BlueBannerView_bv_cornerRadius, 0);
        final int index = ta.getInt(R.styleable.SelectableRoundedImageView_android_scaleType, -1);
        if (index >= 0 && index < sScaleTypeArray.length) {
            mScaleType = sScaleTypeArray[index];
        }
        ta.recycle();

        initView();
    }

    private void initView() {
        mViewPager = new ViewPager2(getContext());
        mBannerAdapter = new BlueBannerAdapter2();
        mViewPager.setAdapter(mBannerAdapter);
        mViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                int realPosition = getRealPosition(position);

                if (mIndicatorViews != null) {
                    for (int i = 0; i < mIndicatorViews.length; i++) {
                        if (i == realPosition) {
                            mIndicatorViews[i].setBackgroundColor(mIndicatorSelectColor);
                        } else {
                            mIndicatorViews[i].setBackgroundColor(mIndicatorColor);
                        }
                    }
                }

                if (mOnItemExposureListener != null) {
                    mOnItemExposureListener.onItemExposure(getItemData(realPosition), realPosition);
                }
            }
        });
//        mViewPager.addOnPageChangeListener(this);

        LayoutParams layoutParams1 = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        addView(mViewPager, layoutParams1);

        mIndicatorLayout = new LinearLayout(getContext());
        mIndicatorLayout.setOrientation(LinearLayout.HORIZONTAL);
        LayoutParams layoutParams2 = new LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams2.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
        layoutParams2.bottomMargin = mIndicatorBottomMargin;
        addView(mIndicatorLayout, layoutParams2);
    }

    private void addIndicators() {
        if (getRealCount() <= 1 || !mShowIndicator) {
            mIndicatorLayout.setVisibility(GONE);
        } else {
            mIndicatorLayout.setVisibility(VISIBLE);

            if (mIndicatorViews == null || mIndicatorViews.length != getRealCount()) {
                mIndicatorViews = new View[getRealCount()];
                if (mIndicatorLayout.getChildCount() > 0) {
                    mIndicatorLayout.removeAllViews();
                }

                for (int i = 0; i < getRealCount(); i++) {
                    View view = new View(getContext());
                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                            mIndicatorSize, mIndicatorSize);
                    if (i != getRealCount() - 1) {
                        layoutParams.rightMargin = mIndicatorPadding;
                    }
                    view.setBackgroundColor(i == 0 ? mIndicatorSelectColor : mIndicatorColor);
                    mIndicatorViews[i] = view;

                    mIndicatorLayout.addView(view, layoutParams);
                }
            }
        }
    }

    /**
     * 设置指示器LayoutParams
     *
     * @param gravity
     * @param left
     * @param top
     * @param right
     * @param bottom
     */
    public void setIndicatorLayoutParams(int gravity, int left, int top, int right, int bottom) {
        LayoutParams lp = (LayoutParams) mIndicatorLayout.getLayoutParams();
        lp.gravity = gravity;
        lp.leftMargin = left;
        lp.topMargin = top;
        lp.rightMargin = right;
        lp.bottomMargin = bottom;
        mIndicatorLayout.setLayoutParams(lp);
    }

    /**
     * 设置banner数据
     *
     * @param urlList
     */
    public void setData(List<String> urlList) {
        mUrlList = urlList;
        addIndicators();
        mBannerAdapter.notifyDataSetChanged();

        if (mOnItemExposureListener != null) {
            int position = getRealPosition(mViewPager.getCurrentItem());
            if (position >= 0 && position < getRealCount()) {
                mOnItemExposureListener.onItemExposure(getItemData(position), position);
            }
        }
    }

    public List<String> getData() {
        return mUrlList;
    }

    /**
     * 是否允许自动播放
     *
     * @param enable
     */
    public void setAutoPlayEnable(boolean enable) {
        mEnableAutoPlay = enable;
        //防止 count 不匹配抛异常
        mBannerAdapter.notifyDataSetChanged();
    }

    public void setAutoPlayTime(int mills) {
        mAutoPlayTime = mills;
    }

    /**
     * 开始自动播放
     */
    public void startAutoPlay() {
        if (mEnableAutoPlay && !mIsAutoPlaying && getRealCount() > 1) {
            mIsAutoPlaying = true;
            mHandler.removeMessages(BlueBannerHandler.MSG_AUTO_PLAY);
            mHandler.sendEmptyMessageDelayed(BlueBannerHandler.MSG_AUTO_PLAY, mAutoPlayTime);
        }
    }

    /**
     * 停止自动播放
     */
    public void stopAutoPlay() {
        if (mEnableAutoPlay && mIsAutoPlaying) {
            mIsAutoPlaying = false;
            mHandler.removeMessages(BlueBannerHandler.MSG_AUTO_PLAY);
        }
    }

    public void scrollToPosition(int position) {
        if (mViewPager != null && getRealCount() > position) {
            //防止 count 不匹配抛异常， 为何count会变未知
            mBannerAdapter.notifyDataSetChanged();
            mViewPager.setCurrentItem(position, false);
        }
    }

    private void autoScroll() {
        if (mEnableAutoPlay && mIsAutoPlaying) {
            int currentItem = mViewPager.getCurrentItem() + 1;
            boolean smoothScroll = true;
            if (currentItem < 0 || currentItem > mBannerAdapter.getItemCount() - 1) {
                currentItem = 0;
                smoothScroll = false;
            }
            mViewPager.setCurrentItem(currentItem, smoothScroll);

            mHandler.sendEmptyMessageDelayed(BlueBannerHandler.MSG_AUTO_PLAY, mAutoPlayTime);
        }
    }

    private String getItemData(int position) {
        return mUrlList != null ? mUrlList.get(position) : null;
    }

    public int getRealCount() {
        return mUrlList != null ? mUrlList.size() : 0;
    }

    private int getRealPosition(int position) {
        int realCount = getRealCount();
        return realCount != 0 ? position % getRealCount() : 0;
    }

    /**
     * 点击监听
     *
     * @param listener
     */
    public void setOnItemClickListener(OnItemClickListener listener) {
        mOnItemClickListener = listener;
    }

    /**
     * 曝光监听
     *
     * @param listener
     */
    public void setOnItemExposureListener(OnItemExposureListener listener) {
        mOnItemExposureListener = listener;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mEnableAutoPlay && getRealCount() > 1) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    stopAutoPlay();
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_OUTSIDE:
                    startAutoPlay();
                    break;
                default:
                    break;
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);

        if (visibility != VISIBLE) {
            stopAutoPlay();
        } else if (getVisibility() == VISIBLE) {
            startAutoPlay();
        }
    }

    private static class BlueBannerHandler extends Handler {

        WeakReference<BlueBannerView> mBannerViewRef;
        static final int MSG_AUTO_PLAY = 1;

        BlueBannerHandler(BlueBannerView bannerView) {
            mBannerViewRef = new WeakReference<>(bannerView);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_AUTO_PLAY:
                    BlueBannerView bannerView = mBannerViewRef.get();
                    if (bannerView != null) {
                        bannerView.autoScroll();
                    }
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }

    private class BlueBannerAdapter extends PagerAdapter {

        LinkedList<ImageView> mRecycledViews = new LinkedList<>();

        @Override
        public int getCount() {
            int count = getRealCount();
            return mEnableAutoPlay && count > 1 ? Integer.MAX_VALUE : count;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return object instanceof View && object == view;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            ImageView itemView;
            if (mRecycledViews.size() == 0) {
                itemView = new ImageView(getContext());
                if (mScaleType != null) {
                    itemView.setScaleType(mScaleType);
                } else {
                    itemView.setScaleType(ImageView.ScaleType.FIT_XY);
                    itemView.setAdjustViewBounds(true);
                }
            } else {
                itemView = mRecycledViews.removeFirst();
            }

            final int realPosition = getRealPosition(position);
            final String url = getItemData(realPosition);

            itemView.setImageResource(R.mipmap.bg_head);
            if (!TextUtils.isEmpty(url)) {
//                itemView.post(() -> Glide.with(getContext()).load(url).into(itemView));
            } else {
                itemView.setImageDrawable(null);
            }

            itemView.setOnClickListener(v -> {
                if (mOnItemClickListener != null) {
                    mOnItemClickListener.onItemClick(url, realPosition);
                }
            });

            container.addView(itemView, ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);

            return itemView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            if (mRecycledViews.size() > 0) {
                mRecycledViews.clear();
            }
            container.removeView((View) object);
            mRecycledViews.add((ImageView) object);
        }

        @Override
        public int getItemPosition(@NonNull Object object) {
            return POSITION_NONE;
        }
    }

    private class BlueBannerAdapter2 extends RecyclerView.Adapter<BaseViewHolder> {

        @NonNull
        @Override
        public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            ImageView itemView = new ImageView(getContext());
            if (mScaleType != null) {
                itemView.setScaleType(mScaleType);
            } else {
                itemView.setScaleType(ImageView.ScaleType.FIT_XY);
                itemView.setAdjustViewBounds(true);
            }
            itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

            BaseViewHolder holder = new BaseViewHolder(itemView);
            itemView.setOnClickListener(v -> {
                if (mOnItemClickListener != null && holder.getAdapterPosition() != RecyclerView.NO_POSITION) {
                    int realPosition = getRealPosition(holder.getAdapterPosition());
                    mOnItemClickListener.onItemClick(getItemData(realPosition), realPosition);
                }
            });

            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {

            final int realPosition = getRealPosition(position);
            final String url = getItemData(realPosition);

            ImageView imageView = (ImageView) holder.itemView;
            imageView.setImageResource(R.mipmap.bg_head);
            if (!TextUtils.isEmpty(url)) {
//                itemView.post(() -> Glide.with(getContext()).load(url).into(itemView));
            } else {
                imageView.setImageDrawable(null);
            }
        }

        @Override
        public int getItemCount() {
            int count = getRealCount();
            return mEnableAutoPlay && count > 1 ? Integer.MAX_VALUE : count;
        }
    }
}
